package yhao.demo.service.erp.workflow.service.task;

import org.apache.commons.lang3.StringUtils;
import yhao.demo.service.erp.workflow.dao.TaskDao;
import yhao.demo.service.erp.workflow.service.pvm.ProcessSearcher;
import yhao.infra.common.util.CommonListUtil;
import yhao.demo.service.erp.workflow.apilist.enums.task.TaskStatus;
import yhao.demo.service.erp.workflow.apilist.form.task.TaskDealPassForm;
import yhao.demo.service.erp.workflow.apilist.form.task.TaskNodeItemForm;
import yhao.demo.service.erp.workflow.apilist.form.task.TaskNodeItemQueryForm;
import yhao.demo.service.erp.workflow.apilist.form.task.TaskStatusChangeForm;
import yhao.demo.service.erp.workflow.apilist.model.flow.FlowNodeModel;
import yhao.demo.service.erp.workflow.apilist.model.task.TaskModel;
import yhao.demo.service.erp.workflow.apilist.model.task.TaskNodeItemModel;

import java.util.List;

public class PassTaskCommand extends TaskCommand {
    private TaskDealPassForm form;
    public PassTaskCommand(TaskDao taskDao, ProcessSearcher processSearcher, TaskDealPassForm form) {
        super(taskDao, processSearcher);
        this.form = form;
    }

    @Override
    protected void initContext() {
        initDealTask(form);
        FlowNodeModel nextNode = null;
        List<FlowNodeModel> nodeList = processSearcher.findNextNodes(
                this.context.getTask().getProcessId(),this.context.getTask().getCurrentNodeId());
        if(!form.isAheadFinish()&&!CommonListUtil.isEmpty(nodeList)){
            nextNode = pickNextNode(form.getPassNodeId(), nodeList);
        }
        this.context.setNextNode(nextNode);
    }

    @Override
    protected Boolean command() {
        TaskModel task = context.getTask();

        checkTask(task);
        checkAssign(task,form);
        checkSubTask(task.getId());

        FlowNodeModel nextNode = context.getNextNode();
        TaskNodeItemQueryForm queryForm = new TaskNodeItemQueryForm();
        queryForm.setTaskId(task.getId());
        queryForm.setNodeId(task.getCurrentNodeId());

        List<TaskNodeItemModel> itemList = taskDao.queryTaskNodeItem(queryForm);
        checkNodeItem(itemList,form.getItemList());

        task.setUpdateOperatorId(form.getOperatorId());
        if(nextNode==null){
            task.setStatus(form.isAheadFinish()?TaskStatus.AHEAD_END:TaskStatus.END);
            taskDao.taskGoToEnd(task);
            addHistory(1,"[流向节点]","结束");
            //如果是子任务，则更改主任务状态
            if(StringUtils.isNotEmpty(task.getParentId())){
                TaskStatusChangeForm form = new TaskStatusChangeForm();
                form.setId(task.getParentId());
                form.setStatus(TaskStatus.RUNNING);
                taskDao.changeTaskStatus(form);
            }
        }else{
            initTaskNodeItem(task.getId(),nextNode);
            //更新任务
            task.setCurrentNodeId(nextNode.getId());
            task.setAssignType(nextNode.getAssignType());
            task.setAssignEntityId(nextNode.getAssignEntityId());
            task.setStatus(TaskStatus.RUNNING);
            //初始化子任务
            if(initSubTask(task,nextNode)){
                task.setStatus(TaskStatus.SUB_TASK);
            }
            taskDao.taskGoToNext(task);
            addHistory(1,"[流向节点]",nextNode.getName());
        }
        closeTaskNodeWarn(task.getId(),context.getCurrentNode());
        updateTaskNodeItem(form.getItemList());
        return true;
    }

    private void checkNodeItem(List<TaskNodeItemModel> itemList, List<TaskNodeItemForm> formList) {
        if(!CommonListUtil.isEmpty(formList)){
            for(TaskNodeItemForm form: formList){
                for(TaskNodeItemModel model:itemList){
                    if(form.getId().equals(model.getId())){ //未持久化的数据保存
                        model.setItemResult(form.getResult());
                        break;
                    }
                }
            }
        }
        for(TaskNodeItemModel model:itemList){
            if( model.isNecessary() &&
                    !model.getItemExceptType().match(model.getItemExcept(),model.getItemResult())){
                throw new RuntimeException("节点事项结果未通过。");
            }
        }
    }
}
